home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
Tools
/
vuser
/
havefun.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-06-20
|
8KB
|
372 lines
/* havefun.c - This module contains the code to do the main i/o handling.
Copyright 1989 by Jeffrey F. Lawhorn (jeffl@berick.uucp)
This file is part of vuser.
vuser is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your
option) any later version.
vuser is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to the
Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(lint)
static char SCCSid[] = "$Id: havefun.c,v 1.1 89/12/15 21:28:52 jeffl Exp $";
#endif
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#if defined(__STDC__)
extern void KillSlave();
extern int DeadSlave();
void Send2MasterPty(char *, int);
void Send2stdout(char *, int);
#else
extern void KillSlave();
extern int DeadSlave();
void Send2MasterPty();
void Send2stdout();
#endif
extern FILE *ScriptFile;
extern FILE *RecordFile;
extern int MasterPty;
extern int Interactive;
char PromptBuf[4096];
char InComingPrompt[8192];
char PromptLookedFor[4096];
int PromptSize = 10;
int PromptCount = 0;
int ICPCount = 0;
int ICPLength = 0;
char *CurrPromptPos = PromptBuf - 1;
char EscapeChar = '@';
#if defined(TIMEOUT_IS_LONG)
long TimeOut = 30;
#else
#include <sys/time.h>
struct timeval TimeOut = {30, 0};
#endif
void Send2ScriptFile(curr, start, stop, size)
char *curr, *start, *stop;
int size;
{
if(curr > stop)
curr = start + 1;
while(size--) {
if(isprint(*curr) && *curr != '\\')
putc(*curr, ScriptFile);
else
switch(*curr) {
case '\n': fputs("\\n", ScriptFile); break;
case '\r': fputs("\\r", ScriptFile); break;
case '\t': fputs("\\t", ScriptFile); break;
case '\f': fputs("\\f", ScriptFile); break;
case '\\': fputs("\\\\", ScriptFile); break;
default: fprintf(ScriptFile, "\\0%03o", *curr); break;
}
if(++curr > stop)
curr = start;
}
putc('\n', ScriptFile);
return;
}
int GetOneChar()
{
char chr = 0;
if(Interactive) {
write(1, "@", 1);
read(0, &chr, 1);
if(chr != EscapeChar)
write(1, &chr, 1);
return((int)chr);
}
return(getchar());
}
int DoEscape(inBuf, cnt)
char *inBuf;
int cnt;
{
int gotChar = -1;
char buf[4096];
if(!cnt)
gotChar = GetOneChar();
else {
gotChar = *inBuf++;
--cnt;
}
if(gotChar == EscapeChar) {
if(ScriptFile) {
fseek(ScriptFile, -1, 1);
putc(EscapeChar, ScriptFile);
putc('\n', ScriptFile);
}
if(!Interactive)
write(1, &gotChar, 1);
return(0);
}
if(Interactive)
Tty2ShellMode();
if(gotChar == '!') {
if(cnt)
strcpy(buf, inBuf);
else
gets(buf);
if(ScriptFile) {
fseek(ScriptFile, -1, 1);
putc('!', ScriptFile);
fputs(buf, ScriptFile);
}
if(!Interactive) {
write(1, "@!", 2);
write(1, buf, strlen(buf));
write(1, "\n", 1);
}
signal(SIGCLD, SIG_DFL);
system(buf);
signal(SIGCLD, DeadSlave);
} else if(gotChar == 't' || gotChar == 'T') {
gets(buf);
if(ScriptFile) {
fseek(ScriptFile, -1, 1);
putc('t', ScriptFile);
fputs(buf, ScriptFile);
}
if(!Interactive) {
write(1, "@t", 2);
write(1, buf, strlen(buf));
write(1, "\n", 1);
}
#if defined(TIMEOUT_IS_LONG)
TimeOut = atol(buf);
#else
TimeOut.tv_sec = atol(buf);
#endif
} else if(gotChar == 'q' || gotChar == 'Q') {
gets(buf);
if(ScriptFile) {
fseek(ScriptFile, -1, 1);
putc('q', ScriptFile);
fputs(buf, ScriptFile);
}
if(!Interactive) {
write(1, "@q", 2);
write(1, buf, strlen(buf));
write(1, "\n", 1);
}
PromptSize = atoi(buf);
}
Tty2ProgramMode();
return(1);
}
void SendResponse();
void GetNextPrompt()
{
int chr = EOF;
ICPLength = 0;
while((chr = getchar()) != EOF) {
switch(chr) {
case '\n': {
if(!ICPLength)
SendResponse();
return;
}
case '\\': {
switch(chr = getchar()) {
case '0': {
chr = ((getchar() - '0') * 64);
chr += ((getchar() - '0') * 8);
chr += (getchar() - '0');
break;
}
case 'n': chr = '\n'; break;
case 'r': chr = '\r'; break;
case 't': chr = '\t'; break;
case 'f': chr = '\f'; break;
case '\\': break;
}
break;
}
}
PromptLookedFor[ICPLength++] = chr;
}
return;
}
void SendResponse()
{
int chr = EOF;
int sendBufCount = 0;
char sendBuf[4096];
while((chr = getchar()) != EOF) {
switch(chr) {
case '\n': {
Send2MasterPty(sendBuf, sendBufCount);
GetNextPrompt();
return;
}
case '\\': {
switch(chr = getchar()) {
case '0': {
chr = ((getchar() - '0') * 64);
chr += ((getchar() - '0') * 8);
chr += (getchar() - '0');
break;
}
case 'n': chr = '\n'; break;
case 'r': chr = '\r'; break;
case 't': chr = '\t'; break;
case 'f': chr = '\f'; break;
case '\\': break;
}
break;
}
}
if(chr == EscapeChar)
if(DoEscape(NULL, 0))
continue;
sendBuf[sendBufCount++] = chr;
}
return;
}
int PromptCompare(ptr1, ptr2, cnt)
char *ptr1, *ptr2;
int cnt;
{
while(cnt-- && *ptr1++ == *ptr2++);
if(!cnt)
return(0);
return(*--ptr1 - *--ptr2);
}
void DoPromptStuff(buf, cnt)
char *buf;
int cnt;
{
while(cnt--) {
InComingPrompt[ICPCount++] = *buf++;
if(ICPCount >= ICPLength) {
if(ICPCount > 8192) {
memcpy(InComingPrompt, InComingPrompt + ICPCount - ICPLength,
ICPLength);
ICPCount = ICPLength;
}
if(!PromptCompare(InComingPrompt + ICPCount - ICPLength,
PromptLookedFor, ICPLength)) {
SendResponse();
ICPCount = 0;
continue;
}
}
}
return;
}
void Send2stdout(buf, cnt)
char *buf;
int cnt;
{
int savedCnt = 0;
if(ScriptFile)
for(; savedCnt < cnt; ++savedCnt) {
if(++CurrPromptPos > PromptBuf + PromptSize)
CurrPromptPos = PromptBuf;
*CurrPromptPos = *(buf + savedCnt);
if(PromptCount++ >= PromptSize)
PromptCount = PromptSize;
}
write(1, buf, cnt);
if(!Interactive)
DoPromptStuff(buf, cnt);
if(RecordFile)
fwrite(buf, 1, cnt, RecordFile);
return;
}
void Send2MasterPty(buf, cnt)
char *buf;
int cnt;
{
static int lastCharSent = -1;
if(ScriptFile) {
if(cnt == 1 && *buf != EscapeChar && PromptCount > 0
&& PromptBuf[PromptCount - 1] == lastCharSent) {
fseek(ScriptFile, -1, 1);
Send2ScriptFile(buf, buf, buf + 1, 1);
} else {
Send2ScriptFile(PromptCount >= PromptSize ?
CurrPromptPos+1:PromptBuf,
PromptBuf, PromptBuf + PromptSize, PromptCount);
CurrPromptPos = PromptBuf - 1;
PromptCount = 0;
Send2ScriptFile(buf, buf, buf + cnt, cnt);
}
lastCharSent = buf[cnt - 1];
}
if(Interactive) {
int pos = 0;
for(; pos < cnt; ++pos)
if(buf[pos] == EscapeChar) {
write(MasterPty, buf, pos);
if(DoEscape(buf + pos + 1, cnt - pos - 1))
return;
}
}
write(MasterPty, buf, cnt);
return;
}
void HaveFun()
{
int readMask = 0, cnt = -1;
char buf[4096];
if(!Interactive)
GetNextPrompt();
while(1) {
readMask = (1 << MasterPty) | Interactive;
if(select(32, &readMask, (int *)NULL, (int *)NULL, &TimeOut) < 0) {
perror("on select: ");
KillSlave();
}
if(readMask & (1 << MasterPty)) {
if((cnt = read(MasterPty, buf, sizeof(buf))) < 0) {
perror("read of master pty: ");
KillSlave();
}
Send2stdout(buf, cnt);
} else if(readMask & 1) {
if((cnt = read(0, buf, sizeof(buf))) < 0) {
perror("read of stdin: ");
KillSlave();
}
Send2MasterPty(buf, cnt);
} else if(!Interactive)
SendResponse();
}
}